package com.brayan.webapp.controller;

import java.io.Serializable;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.inject.Inject;

import org.apache.log4j.Logger;

import com.brayan.webapp.repository.PubRepository;
import com.brayan.webapp.repository.PubThreadRepository;
import com.brayan.webapp.service.auxilliary.CRUDState;
import com.brayan.webapp.model.Pub;
import com.brayan.webapp.model.PubCategory;
import com.brayan.webapp.model.PubThread;
import com.brayan.webapp.model.UploadedImage;
import com.brayan.webapp.service.PubBean;

/**
 * The PubController manages the entire conversation in a view scope. the
 * passed param of the pubId is catched on creation.
 */

@ManagedBean
@ViewScoped
public class PubController implements Serializable {

	private static final long serialVersionUID = 6555461789692254085L;

	private static final String DATE_FORMAT_JSF = "MM d yy";
	private static final String DATE_FORMAT_BEAN = "MMMM d yyy";

	@Inject
	private Logger log;

	@EJB
	private PubBean pubService;
	@Inject
	private PubRepository pubRepository;
	@Inject
	private PubThreadRepository pubThreadRepository;

	/**
	 * Injected fileUploaded. This one is used for images. In particular the
	 * header image.
	 */
//	@Inject
//	private FileUploadController imageUploadController;

	private Pub pub = null;

	// @ManagedProperty(value = "#{param.pubId}")
	private Long id;

	// CRUD State
	// @ManagedProperty(value = "#{param.o}")
	private CRUDState state = CRUDState.V;
	private boolean isUserReadyToPersist = false;

	// Meta
	private String dateOfPub;
	private String mediaSource;
	private String location;
	private int severityLevel;
	private Calendar dateCreated;

	// References
	private PubCategory pubCategory;
	private List<PubThread> pubThreads;

	// Images
	private List<UploadedImage> uploadedImages = new ArrayList<UploadedImage>();
	private String headerImageCaption = "";

	// Content
	private String title;
	private String teaser;
	private String article;

	@PostConstruct
	public void init() {
		String pubIdStr = FacesContext.getCurrentInstance()
				.getExternalContext().getRequestParameterMap().get("pubId");
		String opStr = FacesContext.getCurrentInstance().getExternalContext()
				.getRequestParameterMap().get("o");
		
		if (pubIdStr != null && !pubIdStr.isEmpty() && opStr != null
				&& CRUDState.valueOf(opStr).equals(CRUDState.D)) {
			// Assume a delete
			// CANNOT USE INJECTED INSTANCE IN CONSTRUCTOR BECAUSE INSTANTIATED AFTERWARDS
			log.info("A publication with id {" + pubIdStr
					+ "} is requested to be deleted.");
			setState(CRUDState.D);
		} else if (pubIdStr != null && !pubIdStr.isEmpty()) {
			// If no pubId is provided, assume the user want to create a new
			// one.
			id = Long.valueOf(pubIdStr);
			if (opStr != null && !opStr.isEmpty()
					&& CRUDState.valueOf(opStr) == CRUDState.E)
				setState(opStr);
			log.info("A publication is explicitly requested to be edited.");
		} else {
			// If no pubId is provided, assume the user want to create a new
			// one.
			setState(CRUDState.C);
			log.info("A publication is implicitly (no operation provided) requested to be created.");
		}
		
		if (getId() != null) {
			pub = pubService.getPubById(getId());
			if (pub == null) {
				// TODO Return "no pub found"
			} else {
				setUserReadyToPersist(true);
			}
		} else {
			// if no pub is available, get an empty one
			pub = new Pub();
			setUserReadyToPersist(false);
		}
	}

	/**
	 * This initializing method will not reload an entity, once loaded. To
	 * reload use {@link #reInit(Long)}
	 */
	public void init(Long id) {
		if (id == null || id == 0)
			return;
		setId(id);
		init();
	}

//	public FileUploadController getImageUploadController() {
//		return imageUploadController;
//	}

	/**
	 * Invoke the business logic to save this data. If pub is null or the id is
	 * zero, do not invoke the business logic.
	 */
	public void savePub() {
		if (isReadyToPersist())
			pubService.updatePub(pub);
	}

	private boolean isReadyToPersist() {
		return (pub != null && isUserReadyToPersist());
	}

	// Getter & Setters
	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public CRUDState getState() {
		return state;
	}

	public void setState(CRUDState state) {
		if (state != null)
			this.state = state;
	}

	/**
	 * This method shoudl be accessible by @Role Administrator only.
	 * 
	 * @param state
	 */
	public void setState(String state) {
		if (state != null) {
			this.state = CRUDState.valueOf(state);
		}
	}

	public boolean isInViewState() {
		return this.state == CRUDState.V;
	}

	public boolean isInEditState() {
		boolean isEdited = (this.state == CRUDState.E) ? true : false;
		return isEdited;
	}

	public boolean isInCreateState() {
		return this.state == CRUDState.C;
	}

	public boolean isInDeleteState() {
		return this.state == CRUDState.D;
	}

	public boolean isUserReadyToPersist() {
		return isUserReadyToPersist;
	}

	public void setUserReadyToPersist(boolean isUserReadyToPersist) {
		this.isUserReadyToPersist = isUserReadyToPersist;
	}

	public Date getDateCreated() {
		if (pub != null) {
			dateCreated = pub.getDateCreated();
			return dateCreated.getTime();
		}
		return dateCreated.getTime();
	}

	public String getDateOfPub() {
		if (pub != null) {
			dateOfPub = new SimpleDateFormat(DATE_FORMAT_BEAN).format(pub
					.getpubDate().getInstance());
		}
		return dateOfPub;
	}

	public void setDateOfPub(String strDate) {
		// 09/06/2013
		Date parsedDate = null;
		try {
			parsedDate = new SimpleDateFormat(DATE_FORMAT_BEAN).parse(strDate);
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		Calendar date = new GregorianCalendar();
		date.setTime(parsedDate);
		if (pub != null)
			pub.setPubDate(date);
		savePub();
	}

	public String getMediaSource() {
		if (pub != null)
			mediaSource = pub.getMediaSource();
		return mediaSource;
	}

	public void setMediaSource(String mediaSource) {
		pub.setMediaSource(mediaSource);
		savePub();
	}

	public String getLocation() {
		if (pub != null)
			location = pub.getLocation();
		return location;
	}

	public void setLocation(String location) {
		pub.setLocation(location);
		savePub();
	}

	public int getSeverityLevel() {
		if (pub != null)
			severityLevel = pub.getSeverityLevel();
		return severityLevel;
	}

	public void setSeverityLevel(int severityLevel) {
		pub.setSeverityLevel(severityLevel);
		savePub();
	}

	public PubCategory getPubCategory() {
		if (pub != null)
			this.pubCategory = pub.getPubCategory();
		return this.pubCategory;
	}

	public void setPubCategory(PubCategory pubCategory) {
		this.pubCategory = pubCategory;
		pub.setPubCategory(pubCategory);
		savePub();
	}

	public String getTitle() {
		if (pub != null)
			title = pub.getTitle();
		return title;
	}

	public void setTitle(String title) {
		pub.setTitle(title);
		savePub();
	}

	public String getTeaser() {
		if (pub != null)
			teaser = pub.getTeaser();
		return teaser;
	}

	public void setTeaser(String teaser) {
		pub.setTeaser(teaser);
		savePub();
	}

	public String getArticle() {
		if (pub != null)
			article = pub.getArticle();
		return article;
	}

	public void setArticle(String article) {
		pub.setArticle(article);
		savePub();
	}

	public List<PubThread> getPubThreads() {
		if (pub != null)
			pubThreads = pub.getPubThreads();
		return pubThreads;
	}

	public void setPubThreads(List<PubThread> selectedPubThreads) {
		pub.setPubThreads(selectedPubThreads);
		savePub();
	}

	public String getHeaderImageCaption() {
		return headerImageCaption;
	}

	public void setHeaderImageCaption(String headerImageCaption) {
		this.headerImageCaption = headerImageCaption;
	}

	// HEADER IMAGE UPLOAD
	public UploadedImage getHeaderImage() {
		UploadedImage ui = pub.getUploadedImages().iterator().next();
		return ui;
	}

	public boolean isHeaderImageAvailable() {
		if (pub.getUploadedImages() == null)
			return false;
		return !pub.getUploadedImages().isEmpty();
	}

	/**
	 * Accepting an uploaded header image, will save it immediately to the
	 * database.
	 */
//	public void acceptHeaderImage() {
//		UploadedImage headerImage = imageUploadController.getFiles().get(0);
//		headerImage.setTitle(getHeaderImageCaption());
//		pub.getUploadedImages().add(headerImage);
//		savePub();
//
//		// cleanup the session
//		imageUploadController.clearUploadData();
//	}

	// end: HEADER IMAGE UPLOAD

	public List<Pub> getPubsOfSameThreads() {
		List<Pub> pubs = new ArrayList<Pub>();
		List<PubThread> pubThreads = pubThreadRepository
				.getPubThreadsByPubId(getId());
		for (PubThread pubThread : pubThreads) {
			pubs.addAll(pubRepository.getPubsByThread(pubThread.getId()));
		}

		return pubs;
	}

	/**
	 * Enrich the placeholder text of an input textbox with whatever is needed.
	 * E.g. Css
	 * 
	 * @param placeHolderText
	 * @return
	 */
	public String enrichPlaceholder(String placeHolderText) {
		// Cannot insert empty string into JSTL-variable
		if (placeHolderText.isEmpty())
			return " ";
		StringBuilder enrichedText = new StringBuilder(placeHolderText);
		enrichedText.insert(0, "[");
		enrichedText.append("]");
		return enrichedText.toString();
	}

	public String getCurrentTimeStampFormatted() {
		String formattedDateString = new SimpleDateFormat(DATE_FORMAT_BEAN)
				.format(Calendar.getInstance().getTime());
		return formattedDateString;
	}

	public String getDateFormatting() {
		return DATE_FORMAT_JSF;
	}
}
